﻿using Duende.IdentityModel.Client;
using Joy.Erp.BasicArchives.Core;
using Newtonsoft.Json;
using System;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;

namespace Joy.Erp.BasicArchives.HttpApi.SimplyClient.Core
{
    public static class ApiHandler
    {

        public static async Task<T> HttpGetAsync<T>(string token, string url, Action<string> logfunc = null)
        {
            var client = new HttpClient();
            client.SetBearerToken(token);

            var response = await client.GetAsync(url);
            return await HandResponseAsync<T>(response, url);
        }

        public static async Task<T> HttpPostAsync<T>(string token, string url, object input = null, Action<string> logfunc = null)
        {
            var client = new HttpClient();
            ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, error) => true;
            client.SetBearerToken(token);

            HttpContent httpContent = null;
            if (input != null)
            {
                var content = JsonConvert.SerializeObject(input);
                httpContent = new StringContent(content);
                httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            }

            var response = await client.PostAsync(url, httpContent);
            return await HandResponseAsync<T>(response, url);
        }

        public static async Task<T> HttpPutAsync<T>(string token, string url, object input = null, Action<string> logfunc = null)
        {
            var client = new HttpClient();
            ServicePointManager.ServerCertificateValidationCallback = (sender, cert, chain, error) => true;
            client.SetBearerToken(token);

            HttpContent httpContent = null;
            if (input != null)
            {
                var content = JsonConvert.SerializeObject(input);
                httpContent = new StringContent(content);
                httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            }

            var response = await client.PutAsync(url, httpContent);
            return await HandResponseAsync<T>(response, url);
        }

        public static async Task HttpDeleteAsync(string token, string url, Action<string> logfunc = null)
        {
            var client = new HttpClient();
            client.SetBearerToken(token);

            var response = await client.DeleteAsync(url);
            await HandResponseAsync(response, url);
        }

        private static async Task<T> HandResponseAsync<T>(HttpResponseMessage response, string url)
        {
            var json = await response.Content.ReadAsStringAsync();

            if (response.StatusCode == HttpStatusCode.NoContent) return default(T);
            if (response.StatusCode == HttpStatusCode.Forbidden)
            {
                var errorDto = JsonConvert.DeserializeObject<ErrorDto>(json);
                throw new Exception($"接口{url}返回错误：{errorDto.Error.Message}");
            }
            if (response.StatusCode == HttpStatusCode.InternalServerError) throw new Exception($"服务器内部错误：{url}。响应内容：{json}");
            if (response.StatusCode == HttpStatusCode.Unauthorized) throw new Exception($"用户未授权该方法：{url}");
            if (response.StatusCode != HttpStatusCode.OK) throw new Exception($"请求{url}失败，未处理状态码{response.StatusCode}");


            try
            {
                return JsonConvert.DeserializeObject<T>(json);
            }
            catch (Exception ex)
            {
                throw new Exception($"未能将{url}请求结果{json}转换为对象{typeof(T).FullName}", ex);
            }
        }

        private static async Task HandResponseAsync(HttpResponseMessage response, string url)
        {
            var json = await response.Content.ReadAsStringAsync();

            if (response.StatusCode == HttpStatusCode.Forbidden)
            {
                var errorDto = JsonConvert.DeserializeObject<ErrorDto>(json);
                throw new Exception($"接口{url}返回错误：{errorDto.Error.Message}");
            }
            if (response.StatusCode == HttpStatusCode.InternalServerError) throw new Exception($"服务器内部错误：{url}。响应内容：{json}");
            if (response.StatusCode == HttpStatusCode.Unauthorized) throw new Exception($"用户未授权该方法：{url}");
            if (response.StatusCode != HttpStatusCode.OK) throw new Exception($"请求{url}失败，未处理状态码{response.StatusCode}");
        }
    }
}
